// Copyright Epic Games, Inc. All Rights Reserved.

#include "InteractionStatics.h"

#include "Components/PrimitiveComponent.h"
#include "Engine/OverlapResult.h"
#include "IInteractableTarget.h"
#include "UObject/ScriptInterface.h"

#include UE_INLINE_GENERATED_CPP_BY_NAME(InteractionStatics)

/**
 * 构造函数
 */
UInteractionStatics::UInteractionStatics()
	: Super(FObjectInitializer::Get())
{
}

/**
 * 从可交互目标接口获取Actor
 * @param InteractableTarget 可交互目标接口
 * @return 返回对应的Actor指针
 */
AActor* UInteractionStatics::GetActorFromInteractableTarget(TScriptInterface<IInteractableTarget> InteractableTarget)
{
	if (UObject* Object = InteractableTarget.GetObject()) // 获取接口对象
	{
		if (AActor* Actor = Cast<AActor>(Object)) // 如果对象是Actor
		{
			return Actor; // 返回Actor
		}
		else if (UActorComponent* ActorComponent = Cast<UActorComponent>(Object)) // 如果对象是Actor组件
		{
			return ActorComponent->GetOwner(); // 返回组件的拥有者
		}
		else
		{
			unimplemented(); // 未实现的类型
		}
	}

	return nullptr; // 返回空指针
}

/**
 * 从Actor获取所有可交互目标
 * @param Actor 要检查的Actor
 * @param OutInteractableTargets 输出的可交互目标数组
 */
void UInteractionStatics::GetInteractableTargetsFromActor(AActor* Actor, TArray<TScriptInterface<IInteractableTarget>>& OutInteractableTargets)
{
	// 如果Actor直接可交互，返回该Actor
	TScriptInterface<IInteractableTarget> InteractableActor(Actor);
	if (InteractableActor)
	{
		OutInteractableTargets.Add(InteractableActor); // 添加到输出数组
	}

	// 如果Actor不可交互，它可能有一个具有可交互接口的组件
	TArray<UActorComponent*> InteractableComponents = Actor ? Actor->GetComponentsByInterface(UInteractableTarget::StaticClass()) : TArray<UActorComponent*>(); // 获取所有可交互组件
	for (UActorComponent* InteractableComponent : InteractableComponents) // 遍历所有可交互组件
	{
		OutInteractableTargets.Add(TScriptInterface<IInteractableTarget>(InteractableComponent)); // 添加到输出数组
	}
}

/**
 * 从重叠结果中追加可交互目标
 * @param OverlapResults 重叠结果数组
 * @param OutInteractableTargets 输出的可交互目标数组
 */
void UInteractionStatics::AppendInteractableTargetsFromOverlapResults(const TArray<FOverlapResult>& OverlapResults, TArray<TScriptInterface<IInteractableTarget>>& OutInteractableTargets)
{
	for (const FOverlapResult& Overlap : OverlapResults) // 遍历所有重叠结果
	{
		TScriptInterface<IInteractableTarget> InteractableActor(Overlap.GetActor()); // 从Actor获取可交互接口
		if (InteractableActor)
		{
			OutInteractableTargets.AddUnique(InteractableActor); // 唯一添加到输出数组
		}

		TScriptInterface<IInteractableTarget> InteractableComponent(Overlap.GetComponent()); // 从组件获取可交互接口
		if (InteractableComponent)
		{
			OutInteractableTargets.AddUnique(InteractableComponent); // 唯一添加到输出数组
		}
	}
}

/**
 * 从命中结果中追加可交互目标
 * @param HitResult 命中结果
 * @param OutInteractableTargets 输出的可交互目标数组
 */
void UInteractionStatics::AppendInteractableTargetsFromHitResult(const FHitResult& HitResult, TArray<TScriptInterface<IInteractableTarget>>& OutInteractableTargets)
{
	TScriptInterface<IInteractableTarget> InteractableActor(HitResult.GetActor()); // 从Actor获取可交互接口
	if (InteractableActor)
	{
		OutInteractableTargets.AddUnique(InteractableActor); // 唯一添加到输出数组
	}

	TScriptInterface<IInteractableTarget> InteractableComponent(HitResult.GetComponent()); // 从组件获取可交互接口
	if (InteractableComponent)
	{
		OutInteractableTargets.AddUnique(InteractableComponent); // 唯一添加到输出数组
	}
}